package main

import (
	"bufio"
	"encoding/csv"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"math"
	"math/rand"
	"net/http"
	"os"
	"sort"
	"strconv"
	"strings"
	"time"

	"github.com/paulmach/orb"
	"github.com/paulmach/orb/geo"
	"github.com/paulmach/orb/geojson"

	"gorm.io/driver/postgres"
	"gorm.io/gorm"
)

const earthRadiusKm = 6371.0 // 地球平均半径，单位：千米

// NearestResult 结构体用于解析 JSON 响应
type NearestResult struct {
	Code      string         `json:"code"`
	Waypoints []WaypointInfo `json:"waypoints"`
}

// WaypointInfo 结构体用于解析单个 waypoint 信息
type WaypointInfo struct {
	Hint     string    `json:"hint"`
	Nodes    []int     `json:"nodes"`
	Distance float64   `json:"distance"`
	Name     string    `json:"name"`
	Location []float64 `json:"location"`
}

// BaiduResp body
type BaiduResp struct {
	Status  int     `json:"status"`
	Message string  `json:"message"`
	Results []Place `json:"results"`
}

// Place 地点
type Place struct {
	Name     string   `json:"name"`
	Location Location `json:"location"`
	Address  string   `json:"address"`
	Province string   `json:"province"`
	City     string   `json:"city"`
}

// Location x,y
type Location struct {
	Lat float64 `json:"lat"`
	Lng float64 `json:"lng"`
}

// parseStationNames 解析12306站点名称字符串
func parseStationNames(stationNames string) map[string]string {
	// 定义结果切片
	stations := make(map[string]string)

	// 使用'|'作为分隔符来分割整个字符串
	parts := strings.Split(stationNames, "@")[1:] // 忽略第一个空元素

	// 遍历每个站点信息
	for _, part := range parts {
		info := strings.Split(part, "|")
		if len(info) >= 3 {
			name := info[1] // 站点名称
			code := info[2] // 站点编号
			stations[name] = code
		}
	}

	return stations
}

// readStationNames 从文件中读取站点名称字符串
func readStationNames(filename string) (string, error) {
	file, err := os.Open(filename)
	if err != nil {
		return "", err
	}
	defer file.Close()
	// 设置较大的缓冲区大小
	const maxBufferSize = 1024 * 1024 // 1MB
	scanner := bufio.NewScanner(file)
	scanner.Buffer(make([]byte, maxBufferSize), maxBufferSize)

	var content strings.Builder

	for scanner.Scan() {
		line := scanner.Text()
		content.WriteString(line + "\n") // 添加换行符
	}

	if err := scanner.Err(); err != nil {
		return "", err
	}

	return content.String(), nil
}

// readCSV 读取 CSV 文件内容
func readCSV(filename string) ([][]string, error) {
	file, err := os.Open(filename)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	reader := csv.NewReader(file)
	records, err := reader.ReadAll()
	if err != nil {
		return nil, err
	}

	return records, nil
}

// writeCSV 写入 CSV 文件内容
func writeCSV(filename string, records [][]string) error {
	file, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer file.Close()

	writer := csv.NewWriter(file)
	defer writer.Flush()

	for _, record := range records {
		err := writer.Write(record)
		if err != nil {
			return err
		}
	}

	return nil
}

// callOSRMMatch 调用OSRM的nearest绑路接口
func callOSRMMatch(x, y float64) (float64, float64, error) {
	url := fmt.Sprintf("http://atlasdata.cn:38087/nearest/v1/driving/%f,%f", x, y)

	resp, err := http.Get(url)
	if err != nil {
		return 0, 0, err
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return 0, 0, err
	}

	var result NearestResult
	err = json.Unmarshal(body, &result)
	if err != nil {
		return 0, 0, err
	}

	if len(result.Waypoints) > 0 {
		newX := result.Waypoints[0].Location[0]
		newY := result.Waypoints[0].Location[1]
		return newX, newY, nil
	}

	return 0, 0, fmt.Errorf("no nearest location found")
}

// callBaiduMatch 调用baidu的地点搜索search接口获取站点经纬度
func callBaiduMatch(name string) (float64, float64, error) {
	url := fmt.Sprintf(`http://api.map.baidu.com/place/v2/search?query=%s&region=全国&output=json&ak=3yZlMT3ioSaTaa0kioxwulQrROoN97RV`, name)
	res, err := http.Get(url)
	if err != nil {
		return 0, 0, err
	}
	defer res.Body.Close()

	if res.StatusCode != 200 {
		return 0, 0, fmt.Errorf("HTTP status code: %d", res.StatusCode)
	}

	resp := BaiduResp{}
	body, err := io.ReadAll(res.Body)
	if err != nil {
		return 0, 0, err
	}
	err = json.Unmarshal(body, &resp)
	if err != nil {
		return 0, 0, err
	}

	if len(resp.Results) == 0 {
		return 0, 0, fmt.Errorf("no matched station")
	}
	// 需要坐标变换，否则直接赋值即可
	x, y := Bd09ToWgs84(resp.Results[0].Location.Lng, resp.Results[0].Location.Lat)
	return x, y, nil
}

// 计算两点之间的距离（单位：千米）
func distance(lon1, lat1, lon2, lat2 float64) float64 {
	phi1 := toRadians(lat1)
	phi2 := toRadians(lat2)
	deltaPhi := toRadians(lat2 - lat1)
	deltaLambda := toRadians(lon2 - lon1)

	a := math.Sin(deltaPhi/2)*math.Sin(deltaPhi/2) +
		math.Cos(phi1)*math.Cos(phi2)*math.Sin(deltaLambda/2)*math.Sin(deltaLambda/2)
	c := 2 * math.Atan2(math.Sqrt(a), math.Sqrt(1-a))

	return earthRadiusKm * c
}

// 将角度转换为弧度
func toRadians(degrees float64) float64 {
	return degrees * (math.Pi / 180)
}

// BindStations2Railway站点绑路
func BindStations2Railway() error {
	// 文件名
	stationNamesFile := "station_names.txt"
	parsedStationFile := "parsed_stations.csv"
	osmStationFile := "stations.csv"
	matchedStationFile := "matched_stations.csv"
	failedStationFile := "failed_stations.csv"

	// 读取12306站点名称文件
	stationNames, err := readStationNames(stationNamesFile)
	if err != nil {
		return err
	}
	// 解析并保存站点名称及代码
	parsedStations := parseStationNames(stationNames)
	fmt.Println("Total Parsed Stations:", len(parsedStations))
	records := [][]string{}
	for k, v := range parsedStations {
		records = append(records, []string{k, v})
	}
	err = writeCSV(parsedStationFile, records)
	if err != nil {
		return err
	}
	// 读取osm站点文件
	osmRecords, err := readCSV(osmStationFile)
	if err != nil {
		return err
	}
	// 建立名称为索引
	stations := make(map[string]int)
	for i, record := range osmRecords {
		if len(record) > 3 && record[3] != "" {
			stations[record[3]] = i
		}
	}
	// 开始匹配
	newRecords := [][]string{}
	newRecords = append(newRecords, []string{"ox", "oy", "name", "code", "x", "y"})
	failedRecords := [][]string{}
	i := 0
	for k, v := range parsedStations {
		if idx, ok := stations[k]; ok {
			record := osmRecords[idx]
			x, _ := strconv.ParseFloat(record[0], 64)
			y, _ := strconv.ParseFloat(record[1], 64)
			//调osrm绑路
			newX, newY, err := callOSRMMatch(x, y)
			if err != nil {
				fmt.Printf("--->osrm matching %s error:%s\n", k, err)
			}
			// 校验距离是否大于1km
			dist := distance(x, y, newX, newY)
			if dist > 10 {
				fmt.Printf("--->goto baidu, osm nearest > 10km :%s, %.2f km\n", k, dist)
				// failedRecords = append(failedRecords, []string{k, v})
				// continue
				goto baidu
			}
			//校验完成写入匹配结果列表
			newRecord := []string{record[0], record[1], k, v, fmt.Sprintf("%f", newX), fmt.Sprintf("%f", newY)}
			newRecords = append(newRecords, newRecord)
			if i%100 == 0 {
				fmt.Printf("%d, matched %s to (%f, %f)\n", i, k, newX, newY)
			}
			i++
			continue
		}
	baidu:
		//如果不在osm列表中，先使用百度api匹配
		kw := k + "站"
		x, y, err := callBaiduMatch(kw)
		if err != nil {
			//第二次尝试，使用name增加匹配到行政区的概率
			x, y, err = callBaiduMatch(k)
			if err != nil {
				fmt.Printf("--->baidu matching %s :%s\n", k, err)
				failedRecords = append(failedRecords, []string{k, v})
				continue
			}
		}
		//再使用osrm绑路
		newX, newY, err := callOSRMMatch(x, y)
		if err != nil {
			fmt.Printf("--->osrm matching %s error:%s\n", k, err)
		}
		// 校验距离是否大于1km
		dist := distance(x, y, newX, newY)
		if dist > 10 {
			fmt.Printf("--->nearest dist > 10km: %s, %.2f km\n", k, dist)
			failedRecords = append(failedRecords, []string{k, v})
			continue
		}
		newRecord := []string{fmt.Sprintf("%f", x), fmt.Sprintf("%f", y), k, v, fmt.Sprintf("%f", newX), fmt.Sprintf("%f", newY)}
		newRecords = append(newRecords, newRecord)
		if i%100 == 0 {
			fmt.Printf("%d, matched %s to (%f, %f)\n", i, k, newX, newY)
		}
		i++
	}
	// 写入匹配结果
	err = writeCSV(matchedStationFile, newRecords)
	if err != nil {
		return err
	}
	fmt.Println("Total matched stations:", len(newRecords)-1)
	// 写入失败记录
	err = writeCSV(failedStationFile, failedRecords)
	if err != nil {
		return err
	}
	fmt.Println("Total failed stations:", len(failedRecords))
	return nil
}

// BindAgain 重新匹配失败的站点
func BindAgain(failedStationFile string) error {
	//再次匹配失败的站点
	failedRecords, err := readCSV(failedStationFile)
	if err != nil {
		return err
	}
	if len(failedRecords) == 0 {
		return fmt.Errorf("no failed stations")
	}
	fmt.Println("Total failed stations:", len(failedRecords))
	//记录最后失败的站点信息
	failedRecords2 := [][]string{}
	matchedRecords := [][]string{}
	matchedRecords = append(matchedRecords, []string{"bd_x", "bd_y", "name", "code", "x", "y"})
	for _, record := range failedRecords {
		if len(record) < 2 {
			fmt.Println("failed records error")
			continue
		}
		name, code := record[0], record[1]
		//使用百度api匹配
		kw := name + "站"
		x, y, err := callBaiduMatch(kw)
		if err != nil {
			//第二次尝试，使用name增加匹配到行政区的概率
			x, y, err = callBaiduMatch(name)
			if err != nil {
				fmt.Printf("--->baidu matching %s (%s) Error:%s\n", name, code, err)
				failedRecords2 = append(failedRecords2, []string{name, code})
				continue
			}
		}

		newX, newY, err := callOSRMMatch(x, y)
		if err != nil {
			fmt.Printf("--->osrm matching %s (%s) Error:%s\n", name, code, err)
		}

		// fmt.Printf("matched %s (%s) to (%f, %f)\n", name, code, newX, newY)
		newRecord := []string{fmt.Sprintf("%f", x), fmt.Sprintf("%f", y), name, code, fmt.Sprintf("%f", newX), fmt.Sprintf("%f", newY)}
		matchedRecords = append(matchedRecords, newRecord)
		// break for debug
		// break
	}
	err = writeCSV("matched_stations2.csv", matchedRecords)
	if err != nil {
		return err
	}
	fmt.Println("Total matched stations:", len(matchedRecords)-1)

	err = writeCSV(failedStationFile, failedRecords2)
	if err != nil {
		return err
	}
	fmt.Println("Last failed Stations:", len(failedRecords2))

	return nil
}

func BindX() {
	// 站点绑路
	err := BindStations2Railway()
	if err != nil {
		fmt.Println("BindStations2Railway Error :", err)
	}
	fmt.Println("BindStations2Railway Done")
	// 重新匹配失败的站点
	// 	err := BindAgain(failedStationFile)
	// 	if err != nil {
	// 		fmt.Println("BindAgain Error :", err)
	// 	}
	// 	return
}

// 定义结构体以匹配API返回的数据格式
type Train struct {
	Date             string `json:"date"`
	FromStation      string `json:"from_station"`
	StationTrainCode string `json:"station_train_code"`
	ToStation        string `json:"to_station"`
	TotalNum         string `json:"total_num"`
	TrainNo          string `json:"train_no"`
}

type ApiResponse struct {
	Data     []Train `json:"data"`
	Status   bool    `json:"status"`
	ErrorMsg string  `json:"errorMsg"`
}

// 生成关键词列表
func generateKeywordList() []string {
	var keywordList []string
	// 添加 G
	keywordList = append(keywordList, "G")
	// 从 G1 到 G99
	for i := 1; i <= 99; i++ {
		keywordList = append(keywordList, "G"+strconv.Itoa(i))
	}
	// 添加 D
	keywordList = append(keywordList, "D")
	// 从 D1 到 D99
	for i := 1; i <= 99; i++ {
		keywordList = append(keywordList, "D"+strconv.Itoa(i))
	}
	// 添加 C
	keywordList = append(keywordList, "C")
	// 从 C1 到 C79
	for i := 1; i <= 79; i++ {
		keywordList = append(keywordList, "C"+strconv.Itoa(i))
	}
	// 添加 K
	keywordList = append(keywordList, "K")
	// 从 K1 到 K19
	for i := 1; i <= 19; i++ {
		keywordList = append(keywordList, "K"+strconv.Itoa(i))
	}
	// 从 K71 到 K89
	for i := 71; i <= 89; i++ {
		keywordList = append(keywordList, "K"+strconv.Itoa(i))
	}
	// 添加 T,不需要加数字
	keywordList = append(keywordList, "T")
	// 添加 Z
	keywordList = append(keywordList, "Z")
	// 从 Z1 到 Z9
	for i := 1; i <= 9; i++ {
		keywordList = append(keywordList, "Z"+strconv.Itoa(i))
	}
	// 添加 Y,不需要加数字
	keywordList = append(keywordList, "Y")

	return keywordList
}

// 将 map 转换为切片
func mapToSlice(trainMapList map[string]Train) []Train {
	var trains []Train
	for _, train := range trainMapList {
		trains = append(trains, train)
	}
	// 排序
	sort.Slice(trains, func(i, j int) bool {
		return trains[i].StationTrainCode < trains[j].StationTrainCode
	})
	return trains
}

// 写入 CSV 文件
func writeTrainsToCSV(trains []Train, filename string) error {
	file, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer file.Close()

	writer := csv.NewWriter(file)
	defer writer.Flush()

	// 写入表头
	headers := []string{"date", "from_station", "station_train_code", "to_station", "total_num", "train_no"}
	if err := writer.Write(headers); err != nil {
		return err
	}

	// 写入数据
	for _, train := range trains {
		row := []string{
			train.Date,
			train.FromStation,
			train.StationTrainCode,
			train.ToStation,
			train.TotalNum,
			train.TrainNo,
		}
		if err := writer.Write(row); err != nil {
			return err
		}
	}

	return nil
}

// 将二维字符串切片转换为 Train 切片
func convertToTrains(records [][]string) ([]Train, error) {
	var trains []Train
	for _, record := range records[1:] { // 跳过表头
		train := Train{
			Date:             record[0],
			FromStation:      record[1],
			StationTrainCode: record[2],
			ToStation:        record[3],
			TotalNum:         record[4],
			TrainNo:          record[5],
		}
		trains = append(trains, train)
	}
	return trains, nil
}

// 对 trains.csv 文件进行排序
func SortTrainsByStationTrainCode() {
	// 读取现有 CSV 文件
	existingTrains, err := readCSV("trains.csv")
	if err != nil {
		fmt.Println("Error reading CSV file:", err)
		return
	}

	// 将现有数据转换为 Train 切片
	existingTrainsData, err := convertToTrains(existingTrains)
	if err != nil {
		fmt.Println("Error converting existing trains to Train slice:", err)
		return
	}

	// 对现有数据进行排序
	sort.Slice(existingTrainsData, func(i, j int) bool {
		return existingTrainsData[i].StationTrainCode < existingTrainsData[j].StationTrainCode
	})

	// 将排序后的数据写回 CSV 文件
	if err := writeTrainsToCSV(existingTrainsData, "sorted_trains.csv"); err != nil {
		fmt.Println("Error writing sorted trains to CSV file:", err)
		return
	}
}
func GetTrainList() {
	// 生成关键词列表
	keywordList := generateKeywordList()
	fmt.Printf("Generated Keyword List: %d\n", len(keywordList))
	fmt.Println(keywordList)
	// 示例 URL
	urlTemplate := "https://search.12306.cn/search/v1/train/search?keyword=%s&date=20240925"
	// 初始化 trainMapList
	trainMapList := make(map[string]Train)
	for i, keyword := range keywordList {
		url := fmt.Sprintf(urlTemplate, keyword)
		resp, err := http.Get(url)
		if err != nil {
			fmt.Printf("Error during HTTP request for keyword '%s': %v\n", keyword, err)
			continue
		}
		defer resp.Body.Close()

		body, err := io.ReadAll(resp.Body)
		if err != nil {
			fmt.Printf("Error reading response body for keyword '%s': %v\n", keyword, err)
			continue
		}

		var apiResponse ApiResponse
		err = json.Unmarshal(body, &apiResponse)
		if err != nil {
			fmt.Printf("Error unmarshalling JSON for keyword '%s': %v\n", keyword, err)
			continue
		}
		// 打印解析后的列车信息
		fmt.Printf("%d, Trains for keyword '%s': %d\n", i, keyword, len(apiResponse.Data))
		for _, train := range apiResponse.Data {
			_, ok := trainMapList[train.StationTrainCode]
			if ok {
				continue
			}
			trainMapList[train.StationTrainCode] = train
		}
		du := time.Duration(rand.Intn(100) + 3000)
		time.Sleep(time.Millisecond * du)
	}

	fmt.Println("Train Map List:", len(trainMapList))
	// 将 map 转换为切片
	trains := mapToSlice(trainMapList)
	// 写入 CSV 文件
	filename := "trains.csv"
	if err := writeTrainsToCSV(trains, filename); err != nil {
		fmt.Printf("Error writing to CSV file: %v\n", err)
	} else {
		fmt.Printf("Trains written to %s\n", filename)
	}
}

// 定义返回结构体
type ScheduleResponse struct {
	Status           bool            `json:"status"`
	Httpstatus       int             `json:"httpstatus"`
	Data             ScheduleData    `json:"data"`
	Messages         []interface{}   `json:"messages"`
	ValidateMessages map[string]bool `json:"validateMessages"`
}

type ScheduleData struct {
	Data []ScheduleItem `json:"data"`
}

type ScheduleItem struct {
	StationName      string `json:"station_name"`
	TrainClassName   string `json:"train_class_name"`
	IsChina          string `json:"isChina"`
	ServiceType      string `json:"service_type"`
	EndStationName   string `json:"end_station_name"`
	StopoverTime     string `json:"stopover_time"`
	CountryCode      string `json:"country_code"`
	IsEnabled        bool   `json:"isEnabled"`
	CountryName      string `json:"country_name"`
	ArriveTime       string `json:"arrive_time"`
	StartStationName string `json:"start_station_name"`
	StationTrainCode string `json:"station_train_code"`
	StartTime        string `json:"start_time"`
	StationNo        string `json:"station_no"`
}

func fetchTrainSchedule(trainNo, from, to string) ([]ScheduleItem, error) {

	urlTemplate := "https://kyfw.12306.cn/otn/czxx/queryByTrainNo?train_no=%s&from_station_telecode=%s&to_station_telecode=%s&depart_date=2024-09-25"
	url := fmt.Sprintf(urlTemplate, trainNo, from, to)

	resp, err := http.Get(url)
	if err != nil {
		return nil, fmt.Errorf("error during HTTP request: %v", err)
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("error reading response body: %v", err)
	}

	var scheduleResp ScheduleResponse
	if err := json.Unmarshal(body, &scheduleResp); err != nil {
		return nil, fmt.Errorf("error parsing JSON response: %v", err)
	}

	if !scheduleResp.Status {
		return nil, fmt.Errorf("request failed with status: %v", scheduleResp.Status)
	}

	return scheduleResp.Data.Data, nil
}

func GetSchedule() {
	//1、parsed_stations.csv中的station code
	stationRecords, err := readCSV("parsed_stations.csv")
	if err != nil {
		log.Fatal(err)
	}
	stationMapList := make(map[string]string)
	for _, record := range stationRecords[1:] {
		if len(record) == 2 {
			stationMapList[record[0]] = record[1]
		}
	}
	//2、从trans.csv文件中获取出发站和到达站并匹配telecode
	trainRecords, err := readCSV("trains.csv")
	if err != nil {
		log.Fatal(err)
	}
	// 3、获取列车时刻表scheduleRecords
	scheduleRecords := [][]string{}
	scheduleRecord := []string{"train_no", "station_train_code", "from_station", "to_station", "total_num", "station_name", "start_time", "arrive_time", "stopover_time", "station_no"}
	scheduleRecords = append(scheduleRecords, scheduleRecord)
	//只查高铁
	// subTrainRecords := [][]string{}
	// for _, record := range trainRecords[1:] {
	// 	if len(record) == 6 && strings.HasPrefix(record[2], "G") {
	// 		subTrainRecords = append(subTrainRecords, record)
	// 	}
	// }
	// for i, record := range subTrainRecords {
	for i, record := range trainRecords[1:] {
		train := Train{
			FromStation:      record[1],
			StationTrainCode: record[2],
			ToStation:        record[3],
			TotalNum:         record[4],
			TrainNo:          record[5],
		}
		fromStation := strings.ReplaceAll(train.FromStation, " ", "")
		fromCode, ok := stationMapList[fromStation]
		if !ok {
			log.Println("Error: station not found:", train.FromStation)
			// continue
			fromCode = "BJP"
		}
		toStation := strings.ReplaceAll(train.ToStation, " ", "")
		toCode, ok := stationMapList[toStation]
		if !ok {
			log.Println("Error: station not found:", train.ToStation)
			// continue
			toCode = "SHH"
		}
		//4、发送请求并解析
		scheduleData, err := fetchTrainSchedule(train.TrainNo, fromCode, toCode)
		if err != nil {
			log.Println("Error fetching schedule:", err)
		}
		//5、组织时刻表数据
		fmt.Printf("idx,station_no:")
		for j, item := range scheduleData {
			record := []string{
				train.TrainNo,
				train.StationTrainCode,
				train.FromStation,
				train.ToStation,
				train.TotalNum,
				item.StationName,
				item.StartTime,
				item.ArriveTime,
				item.StopoverTime,
				item.StationNo,
			}
			scheduleRecords = append(scheduleRecords, record)
			fmt.Printf("(%d,%s),", j, item.StationNo)
		}
		fmt.Println()
		fmt.Printf("idx:%d, StationTrainCode:%s\n", i, train.StationTrainCode)
		if (i+1)%1000 == 0 {
			sufix := fmt.Sprintf("%d", i-999)
			filename := "schedule_" + sufix + ".csv"
			if err := writeCSV(filename, scheduleRecords); err != nil {
				fmt.Printf("Error writing to CSV file: %v\n", err)
			} else {
				fmt.Printf("Trains written to %s\n", filename)
			}
			//重新初始化
			scheduleRecords = [][]string{}
			scheduleRecord = []string{"train_no", "station_train_code", "from_station", "to_station", "total_num", "station_name", "start_time", "arrive_time", "stopover_time", "station_no"}
			scheduleRecords = append(scheduleRecords, scheduleRecord)
		}
		du := time.Duration(rand.Intn(100) + 1000)
		time.Sleep(time.Millisecond * du)
	}

	last := (len(trainRecords) / 1000) * 1000
	filename := "schedule_" + fmt.Sprintf("%d", last) + ".csv"
	if err := writeCSV(filename, scheduleRecords); err != nil {
		fmt.Printf("Error writing to CSV file: %v\n", err)
	} else {
		fmt.Printf("Trains written to %s\n", filename)
	}
}

type Schedule struct {
	TrainNo          string
	StationTrainCode string
	FromStation      string
	ToStation        string
	TotalNum         int
	StationName      string
	StartTime        string
	ArriveTime       string
	StopoverTime     string
	StationNo        string
}

type Station struct {
	Ox   float64
	Oy   float64
	Name string
	Code string
	X    float64
	Y    float64
}

func parseSchedules(records [][]string) map[string][]Schedule {
	var schedules []Schedule
	for i, record := range records {
		if i == 0 {
			continue
		} // 跳过标题行
		totalNum, _ := strconv.Atoi(record[4])
		schedules = append(schedules, Schedule{
			TrainNo:          record[0],
			StationTrainCode: record[1],
			FromStation:      record[2],
			ToStation:        record[3],
			TotalNum:         totalNum,
			StationName:      record[5],
			StartTime:        record[6],
			ArriveTime:       record[7],
			StopoverTime:     record[8],
			StationNo:        record[9],
		})
	}
	scheduleMapList := map[string][]Schedule{}
	for _, schedule := range schedules {
		scheduleMapList[schedule.StationTrainCode] = append(scheduleMapList[schedule.StationTrainCode], schedule)
	}
	return scheduleMapList
}

func parseStations(records [][]string) map[string]Station {
	var stations []Station
	for i, record := range records {
		if i == 0 {
			continue
		} // 跳过标题行
		ox, _ := strconv.ParseFloat(record[0], 64)
		oy, _ := strconv.ParseFloat(record[1], 64)
		x, _ := strconv.ParseFloat(record[4], 64)
		y, _ := strconv.ParseFloat(record[5], 64)
		stations = append(stations, Station{
			Ox:   ox,
			Oy:   oy,
			Name: record[2],
			Code: record[3],
			X:    x,
			Y:    y,
		})
	}
	stationMapList := map[string]Station{}
	for _, station := range stations {
		stationMapList[station.Name] = station
	}
	return stationMapList
}

func initDB() *gorm.DB {
	dsn := "host=atlasdata.cn user=postgres password=onemap dbname=railway port=5432 sslmode=disable TimeZone=Asia/Shanghai"
	db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
	if err != nil {
		panic("failed to connect database")
	}

	db.AutoMigrate(&Schedule{}) // 自动迁移模型
	return db
}

// calculateSegTimestamps 计算区间时间戳 interTime 为区间时间间隔 正值 单位为秒 默认为 60
func calculateSegTimestamps(start, end int, line orb.LineString, interTime int) []interface{} {
	drivingTime := end - start
	// fmt.Printf("drivingTime(%d - %d)=%ds\n", end, start, drivingTime)
	lineLength := geo.Length(line)
	// fmt.Printf("lineLength:%.2f\n", lineLength)
	interNum := drivingTime / interTime
	// fmt.Printf("interNum:%d\n", interNum)
	lengthPerMinute := lineLength / float64(interNum)
	// fmt.Printf("lengthPerMinute:%.2f\n", lengthPerMinute)
	segments := []interface{}{}
	segStart := map[string]interface{}{
		"coordinates": line[0],
		"timestamp":   start,
	}
	// fmt.Printf("seg-%d,dist:%.2fkm, val:%v\n", 0, 0.0, segStart)
	segments = append(segments, segStart)
	for i := 1; i < interNum; i++ {
		dist := lengthPerMinute * float64(i)
		pt, _ := geo.PointAtDistanceAlongLine(line, dist)
		seg := map[string]interface{}{
			"coordinates": pt,
			"timestamp":   start + interTime*i,
		}
		// fmt.Printf("seg-%d,dist:%.2fkm, val:%v\n", i, dist/1000, seg)
		segments = append(segments, seg)
	}
	segEnd := map[string]interface{}{
		"coordinates": line[len(line)-1],
		"timestamp":   end,
	}
	// fmt.Printf("seg-%d,dist:%.2fkm, val:%v\n", interNum, lineLength/1000, segEnd)
	segments = append(segments, segEnd)

	return segments
}

// 将时间字符串转换为 Unix 时间戳
func timeToUnixTimestamp(timeStr string) int {
	// 假设所有时间都在 2024-09-25 这一天
	fullTimeStr := "2024-09-25 " + timeStr
	t, err := time.Parse("2006-01-02 15:04", fullTimeStr)
	if err != nil {
		return 0
	}
	return int(t.Unix())
}

func writeStationsToGeojson() {
	// read stations from csv
	stationsRecords, err := readCSV("data/matched_stations.csv")
	if err != nil {
		fmt.Println("Error reading matched_stations.csv:", err)
		return
	}
	//write stations to geojson format
	//write stations names to jsonarray, eg.["750291","750225","750657"]
	stFc := geojson.NewFeatureCollection()
	stList := []string{}
	for _, record := range stationsRecords[1:] {
		name := record[2]
		x, _ := strconv.ParseFloat(record[4], 64)
		y, _ := strconv.ParseFloat(record[5], 64)
		ft := geojson.NewFeature(orb.Point{x, y})
		ft.Properties["stopId"] = name
		ft.Properties["name"] = name
		stFc.Append(ft)
		stList = append(stList, name)
	}
	// 将GeoJSON数据写入文件
	stData, err := stFc.MarshalJSON()
	if err != nil {
		fmt.Println("Error marshaling GeoJSON:", err)
		return
	}
	err = os.WriteFile("stations.geojson", stData, 0644)
	if err != nil {
		fmt.Println("Error writing tripData file:", err)
		return
	}
	fmt.Println("stations.geojson written successfully.")
	// 将stations name 写入文件
	stListJson, _ := json.Marshal(stList)
	err = os.WriteFile("station_list.json", stListJson, 0644)
	if err != nil {
		fmt.Println("Error writing stListJson file:", err)
		return
	}
	fmt.Println("stListJson written successfully.")
}

// TripData deckgl trips-layer data format
type TripData struct {
	StartTimestamp int                      `json:"startTimestamp"`
	LoopLength     int                      `json:"loopLength"`
	TimeMultiplier float64                  `json:"timeMultiplier"`
	Trips          []map[string]interface{} `json:"trips"`
}

// RouteResp osrm route response struct
type RouteResp struct {
	Code   string `json:"code"`
	Routes []struct {
		Geometry struct {
			Coordinates [][]float64 `json:"coordinates"`
			Type        string      `json:"type"`
		} `json:"geometry"`
		Legs []struct {
			Steps []struct {
			} `json:"steps"`
			Summary  string  `json:"summary"`
			Weight   float64 `json:"weight"`
			Duration float64 `json:"duration"`
			Distance float64 `json:"distance"`
		} `json:"legs"`
		WeightName string  `json:"weight_name"`
		Weight     float64 `json:"weight"`
		Duration   float64 `json:"duration"`
		Distance   float64 `json:"distance"`
	} `json:"routes"`
	Waypoints []struct {
		Hint     string    `json:"hint"`
		Distance float64   `json:"distance"`
		Name     string    `json:"name"`
		Location []float64 `json:"location"`
	} `json:"waypoints"`
}

func MakeTripsDataSimp() {
	// scheduleRecords, err := readCSV("schedules_test.csv")
	scheduleRecords, err := readCSV("schedules_nanjing.csv")
	if err != nil {
		fmt.Println("Error reading schedules_nanjing.csv:", err)
		return
	}
	stationsRecords, err := readCSV("data/matched_stations.csv")
	if err != nil {
		fmt.Println("Error reading matched_stations.csv:", err)
		return
	}
	schedules := parseSchedules(scheduleRecords)
	stations := parseStations(stationsRecords)
	fmt.Printf("stations:%#v\n", stations["南京"])
	fc := geojson.NewFeatureCollection()
	startTimestamp := timeToUnixTimestamp("00:00")
	fmt.Println("startTimestamp:", startTimestamp)
	// 示例数据
	tripData := TripData{
		StartTimestamp: startTimestamp - 8*60*60,
		LoopLength:     12 * 60 * 60,
		TimeMultiplier: 1.0,
	}
	trainNum := 0
	for code, schedule := range schedules {
		if len(schedule) < 2 {
			continue
		}
		// if !strings.HasPrefix(code, "G") {
		// 	continue
		// }
		fmt.Printf("%s:%s->%s,%d\n", code, schedule[0].FromStation, schedule[0].ToStation, len(schedule))
		trainNum++
		for i := 1; i < len(schedule); i++ {
			from := schedule[i-1]
			to := schedule[i]
			fromName := from.StationName
			toName := to.StationName
			fromNo := from.StationNo
			toNo := to.StationNo
			fromLng, fromLat := stations[fromName].X, stations[fromName].Y
			if fromLng == 0 || fromLat == 0 {
				continue
			}
			toLng, toLat := stations[toName].X, stations[toName].Y
			if toLng == 0 || toLat == 0 {
				continue
			}
			// fmt.Printf("seg%d, %s(%s)->%s(%s):s(%f,%f)->e(%f,%f)\n", i, fromName, fromNo, toName, toNo, fromLng, fromLat, toLng, toLat)
			line := orb.LineString([]orb.Point{{fromLng, fromLat}, {toLng, toLat}})
			dist := geo.Length(line)
			if dist > 500000 {
				fmt.Println("Error: distance too long > 500km")
				continue
			}
			// 将 LineString 转换为 GeoJSON
			feature := geojson.NewFeature(line)
			properties := map[string]interface{}{
				"code":           code,
				"fromName":       fromName,
				"toName":         toName,
				"fromStartTime":  from.StartTime,
				"toStartTime":    to.StartTime,
				"fromArriveTime": from.ArriveTime,
				"toArriveTime":   to.ArriveTime,
				"fromNo":         fromNo,
				"toNo":           toNo,
				"fromLng":        fromLng,
				"fromLat":        fromLat,
				"toLng":          toLng,
				"toLat":          toLat,
			}
			feature.Properties = properties
			fc.Append(feature)

			// 计算时间戳
			// fmt.Printf("calculateTimestamps, fromStartTime:%s,toArriveTime:%s\n", from.StartTime, to.ArriveTime)
			// timestamps := calculateTimestamps(from.StartTime, to.ArriveTime, line)
			// 将时间字符串转换为时间戳
			fromTimestamp := timeToUnixTimestamp(from.StartTime)
			toTimestamp := timeToUnixTimestamp(to.ArriveTime)
			startTime := fromTimestamp - startTimestamp
			endTime := toTimestamp - startTimestamp
			segments := []interface{}{
				map[string]interface{}{
					"coordinates": line[0],
					"timestamp":   startTime,
				},
				map[string]interface{}{
					"coordinates": line[1],
					"timestamp":   endTime,
				},
			}
			trips := map[string]interface{}{
				"nodes":     []string{fromName, toName},
				"vehicleId": from.StationTrainCode,
				"startTime": startTime,
				"endTime":   endTime,
				"segments":  segments,
			}
			if endTime > tripData.LoopLength {
				tripData.LoopLength = endTime
			}
			tripData.Trips = append(tripData.Trips, trips)
		}
	}
	fmt.Printf("number of trains passing though nanjing:%d\n", trainNum)
	// 将GeoJSON数据写入文件
	geoJSONBytes, err := fc.MarshalJSON()
	if err != nil {
		fmt.Println("Error marshaling GeoJSON:", err)
		return
	}
	err = os.WriteFile("segments_simp.geojson", geoJSONBytes, 0644)
	if err != nil {
		fmt.Println("Error writing GeoJSON file:", err)
		return
	}
	fmt.Println("GeoJSON file generated successfully.")

	//tripData写到文件
	tripDataBytes, err := json.Marshal(tripData)
	if err != nil {
		fmt.Println("Error marshaling tripData:", err)
		return
	}
	err = os.WriteFile("trips_simp.json", tripDataBytes, 0644)
	if err != nil {
		fmt.Println("Error writing tripData file:", err)
		return
	}
	fmt.Println("tripData file generated successfully.")
	fmt.Println("Data processed and saved.")
}

func MakeTripsDataMinute() {
	// scheduleRecords, err := readCSV("schedules_test.csv")
	scheduleRecords, err := readCSV("schedules_nanjing.csv")
	if err != nil {
		fmt.Println("Error reading schedules_nanjing.csv:", err)
		return
	}
	stationsRecords, err := readCSV("data/matched_stations.csv")
	if err != nil {
		fmt.Println("Error reading matched_stations.csv:", err)
		return
	}
	schedules := parseSchedules(scheduleRecords)
	stations := parseStations(stationsRecords)
	fmt.Printf("stations:%#v\n", stations["南京"])
	fc := geojson.NewFeatureCollection()
	startTimestamp := timeToUnixTimestamp("00:00")
	fmt.Println("startTimestamp:", startTimestamp)
	// 示例数据
	tripData := TripData{
		StartTimestamp: startTimestamp - 8*60*60,
		LoopLength:     12 * 60 * 60,
		TimeMultiplier: 1.0,
	}
	trainNum := 0
	for code, schedule := range schedules {
		if len(schedule) < 2 || len(schedule) > 9 {
			continue
		}
		if strings.HasPrefix(code, "K") || strings.HasPrefix(code, "T") || strings.HasPrefix(code, "Z") {
			continue
		}
		// if !strings.HasPrefix(code, "G") {
		// 	continue
		// }
		//code正则表达式，只选择G1**、G7开头
		// if !regexp.MustCompile(`^(G1\d{2}$|G7)`).MatchString(code) {
		// 	continue
		// }
		//G1-G999
		// if !regexp.MustCompile(`^G\d{3}$`).MatchString(code) {
		// 	continue
		// }
		// if !strings.HasPrefix(schedule[0].StationName, "南京") {
		// 	continue
		// }
		fmt.Printf("%s:%s->%s,%d\n", code, schedule[0].FromStation, schedule[0].ToStation, len(schedule))
		trainNum++
		for i := 1; i < len(schedule); i++ {
			from := schedule[i-1]
			to := schedule[i]
			fromName := from.StationName
			toName := to.StationName
			fromNo := from.StationNo
			toNo := to.StationNo
			fromLng, fromLat := stations[fromName].X, stations[fromName].Y
			toLng, toLat := stations[toName].X, stations[toName].Y
			// fmt.Printf("seg%d, %s(%s)->%s(%s):s(%f,%f)->e(%f,%f)\n", i, fromName, fromNo, toName, toNo, fromLng, fromLat, toLng, toLat)
			//调用接口
			//http://atlasdata.cn:38087/route/v1/driving/116.76681518554689,31.719990390851365;117.27493286132812,32.02088472086091?overview=full&geometries=geojson
			urlTemplate := "http://atlasdata.cn:38087/route/v1/driving/%f,%f;%f,%f?overview=full&geometries=geojson"
			url := fmt.Sprintf(urlTemplate, fromLng, fromLat, toLng, toLat)
			resp, err := http.Get(url)
			if err != nil {
				fmt.Println("Error making HTTP request:", err)
				continue
			}
			defer resp.Body.Close()
			body, err := io.ReadAll(resp.Body)
			if err != nil {
				fmt.Println("Error reading response body:", err)
				continue
			}
			var respObj RouteResp
			if err := json.Unmarshal(body, &respObj); err != nil {
				fmt.Println("Error unmarshalling response body:", err)
				continue
			}
			if len(respObj.Routes) > 0 {
				route := respObj.Routes[0]
				line := orb.LineString([]orb.Point{})
				// 创建 LineString
				for _, coord := range route.Geometry.Coordinates {
					line = append(line, orb.Point{coord[0], coord[1]})
				}
				// 将 LineString 转换为 GeoJSON
				feature := geojson.NewFeature(line)
				properties := map[string]interface{}{
					"code":           code,
					"fromName":       fromName,
					"toName":         toName,
					"fromStartTime":  from.StartTime,
					"toStartTime":    to.StartTime,
					"fromArriveTime": from.ArriveTime,
					"toArriveTime":   to.ArriveTime,
					"fromNo":         fromNo,
					"toNo":           toNo,
					"fromLng":        fromLng,
					"fromLat":        fromLat,
					"toLng":          toLng,
					"toLat":          toLat,
				}
				feature.Properties = properties
				fc.Append(feature)

				// 计算区间时间戳
				// fmt.Printf("fromStartTime:%s->toArriveTime:%s\n", from.StartTime, to.ArriveTime)
				fromTimestamp := timeToUnixTimestamp(from.StartTime)
				if fromTimestamp == 0 {
					fromTimestamp = timeToUnixTimestamp(from.ArriveTime)
					if fromTimestamp == 0 {
						fmt.Println("Error: from start and arrive time are empty")
						continue
					}
				}
				toTimestamp := timeToUnixTimestamp(to.ArriveTime)
				if toTimestamp == 0 {
					toTimestamp = timeToUnixTimestamp(to.StartTime)
					if toTimestamp == 0 {
						fmt.Println("Error: to start and arrive time are empty")
						continue
					}
				}
				// fmt.Printf("from:%d->to:%d\n", fromTimestamp, toTimestamp)
				startTime := fromTimestamp - startTimestamp
				endTime := toTimestamp - startTimestamp
				// fmt.Printf("startTimestamp:%d->endTimestamp:%d\n", startTime, endTime)
				const interTime = 60
				segments := calculateSegTimestamps(startTime, endTime, line, interTime)
				trips := map[string]interface{}{
					"nodes":     []string{fromName, toName},
					"vehicleId": from.StationTrainCode,
					"startTime": startTime,
					"endTime":   endTime,
					"segments":  segments,
				}
				if endTime > tripData.LoopLength {
					tripData.LoopLength = endTime
				}
				tripData.Trips = append(tripData.Trips, trips)
			}
			// break //for debug
		}
		// if trainNum > 999 {
		// 	break
		// }
	}
	fmt.Printf("Passing though trains:%d\n", trainNum)
	// 将GeoJSON数据写入文件
	geoJSONBytes, err := fc.MarshalJSON()
	if err != nil {
		fmt.Println("Error marshaling GeoJSON:", err)
		return
	}
	err = os.WriteFile("segments_minute.geojson", geoJSONBytes, 0644)
	if err != nil {
		fmt.Println("Error writing GeoJSON file:", err)
		return
	}
	fmt.Println("GeoJSON file generated successfully.")

	//tripData写到文件
	tripDataBytes, err := json.Marshal(tripData)
	if err != nil {
		fmt.Println("Error marshaling tripData:", err)
		return
	}
	err = os.WriteFile("trips_minute.json", tripDataBytes, 0644)
	if err != nil {
		fmt.Println("Error writing tripData file:", err)
		return
	}
	fmt.Println("tripData file generated successfully.")
	fmt.Println("Data processed and saved.")
}

func MakeTripsDataSecond() {
	// scheduleRecords, err := readCSV("schedules_test.csv")
	scheduleRecords, err := readCSV("schedules_nanjing.csv")
	if err != nil {
		fmt.Println("Error reading schedules_nanjing.csv:", err)
		return
	}
	stationsRecords, err := readCSV("data/matched_stations.csv")
	if err != nil {
		fmt.Println("Error reading matched_stations.csv:", err)
		return
	}
	schedules := parseSchedules(scheduleRecords)
	stations := parseStations(stationsRecords)
	fmt.Printf("stations:%#v\n", stations["南京"])
	fc := geojson.NewFeatureCollection()
	startTimestamp := timeToUnixTimestamp("00:00")
	fmt.Println("startTimestamp:", startTimestamp)
	// 示例数据
	tripData := TripData{
		StartTimestamp: startTimestamp - 8*60*60,
		LoopLength:     12 * 60 * 60,
		TimeMultiplier: 1.0,
	}
	// filterMap := map[string]bool{}
	trainNum := 0
	for code, schedule := range schedules {
		if len(schedule) < 2 || len(schedule) > 9 {
			continue
		}
		if strings.HasPrefix(code, "K") || strings.HasPrefix(code, "T") || strings.HasPrefix(code, "Z") {
			continue
		}
		if !strings.HasPrefix(schedule[0].StationName, "南京") {
			continue
		}
		// id := fmt.Sprintf("%s-%s", schedule[0].FromStation, schedule[0].ToStation)
		// if _, ok := filterMap[id]; ok {
		// 	continue
		// }
		// filterMap[id] = true
		//只选择G1**
		// if !regexp.MustCompile(`^G1\d{2}$`).MatchString(code) {
		// 	continue
		// }
		// 只选择G7开头
		// if !regexp.MustCompile(`^G7`).MatchString(code) {
		// 	continue
		// }
		if !strings.HasPrefix(schedule[0].StationName, "南京") {
			continue
		}
		fmt.Printf("%s:%s->%s,%s,%d\n", code, schedule[0].FromStation, schedule[0].ToStation, schedule[0].StartTime, len(schedule))
		trainNum++
		for i := 1; i < len(schedule); i++ {
			from := schedule[i-1]
			to := schedule[i]
			fromName := from.StationName
			toName := to.StationName
			fromNo := from.StationNo
			toNo := to.StationNo
			fromLng, fromLat := stations[fromName].X, stations[fromName].Y
			toLng, toLat := stations[toName].X, stations[toName].Y
			// fmt.Printf("seg%d, %s(%s)->%s(%s):s(%f,%f)->e(%f,%f)\n", i, fromName, fromNo, toName, toNo, fromLng, fromLat, toLng, toLat)
			//调用接口
			//http://atlasdata.cn:38087/route/v1/driving/116.76681518554689,31.719990390851365;117.27493286132812,32.02088472086091?overview=full&geometries=geojson
			urlTemplate := "http://atlasdata.cn:38087/route/v1/driving/%f,%f;%f,%f?overview=full&geometries=geojson"
			url := fmt.Sprintf(urlTemplate, fromLng, fromLat, toLng, toLat)
			resp, err := http.Get(url)
			if err != nil {
				fmt.Println("Error making HTTP request:", err)
				continue
			}
			defer resp.Body.Close()
			body, err := io.ReadAll(resp.Body)
			if err != nil {
				fmt.Println("Error reading response body:", err)
				continue
			}
			var respObj RouteResp
			if err := json.Unmarshal(body, &respObj); err != nil {
				fmt.Println("Error unmarshalling response body:", err)
				continue
			}
			if len(respObj.Routes) > 0 {
				route := respObj.Routes[0]
				line := orb.LineString([]orb.Point{})
				// 创建 LineString
				for _, coord := range route.Geometry.Coordinates {
					line = append(line, orb.Point{coord[0], coord[1]})
				}
				// 将 LineString 转换为 GeoJSON
				feature := geojson.NewFeature(line)
				properties := map[string]interface{}{
					"code":           code,
					"fromName":       fromName,
					"toName":         toName,
					"fromStartTime":  from.StartTime,
					"toStartTime":    to.StartTime,
					"fromArriveTime": from.ArriveTime,
					"toArriveTime":   to.ArriveTime,
					"fromNo":         fromNo,
					"toNo":           toNo,
					"fromLng":        fromLng,
					"fromLat":        fromLat,
					"toLng":          toLng,
					"toLat":          toLat,
				}
				feature.Properties = properties
				fc.Append(feature)

				// 计算区间时间戳
				// fmt.Printf("fromStartTime:%s->toArriveTime:%s\n", from.StartTime, to.ArriveTime)
				fromTimestamp := timeToUnixTimestamp(from.StartTime)
				if fromTimestamp == 0 {
					fromTimestamp = timeToUnixTimestamp(from.ArriveTime)
					if fromTimestamp == 0 {
						fmt.Println("Error: from start and arrive time are empty")
						continue
					}
				}
				toTimestamp := timeToUnixTimestamp(to.ArriveTime)
				if toTimestamp == 0 {
					toTimestamp = timeToUnixTimestamp(to.StartTime)
					if toTimestamp == 0 {
						fmt.Println("Error: to start and arrive time are empty")
						continue
					}
				}
				// fmt.Printf("from:%d->to:%d\n", fromTimestamp, toTimestamp)
				startTime := fromTimestamp - startTimestamp
				endTime := toTimestamp - startTimestamp
				// fmt.Printf("startTimestamp:%d->endTimestamp:%d\n", startTime, endTime)
				const interTime = 10
				segments := calculateSegTimestamps(startTime, endTime, line, interTime)
				trips := map[string]interface{}{
					"nodes":     []string{fromName, toName},
					"vehicleId": from.StationTrainCode,
					"startTime": startTime,
					"endTime":   endTime,
					"segments":  segments,
				}
				if endTime > tripData.LoopLength {
					tripData.LoopLength = endTime
				}
				tripData.Trips = append(tripData.Trips, trips)
			}
			// break //for debug
		}
		// if trainNum > 99 {
		// 	break
		// }
	}
	fmt.Printf("Passing though trains:%d\n", trainNum)
	// 将GeoJSON数据写入文件
	geoJSONBytes, err := fc.MarshalJSON()
	if err != nil {
		fmt.Println("Error marshaling GeoJSON:", err)
		return
	}
	err = os.WriteFile("segments_sec.geojson", geoJSONBytes, 0644)
	if err != nil {
		fmt.Println("Error writing GeoJSON file:", err)
		return
	}
	fmt.Println("GeoJSON file generated successfully.")

	//tripData写到文件
	tripDataBytes, err := json.Marshal(tripData)
	if err != nil {
		fmt.Println("Error marshaling tripData:", err)
		return
	}
	err = os.WriteFile("trips_sec.json", tripDataBytes, 0644)
	if err != nil {
		fmt.Println("Error writing tripData file:", err)
		return
	}
	fmt.Println("tripData file generated successfully.")
	fmt.Println("Data processed and saved.")
}

func getCount(db *gorm.DB) (int64, error) {
	var count int64
	err := db.Model(&Schedule{}).Count(&count).Error
	if err != nil {
		return 0, err
	}
	return count, nil
}

// saveSchedulesToCSV 导出全部南京的数据
func saveSchedulesToCSV(db *gorm.DB, filePath string) error {
	// 查询所有 Schedule 记录
	var schedules []Schedule

	// err := db.Table("schedules_nj").Find(&schedules).Error
	err := db.Table("schedules_all").Find(&schedules).Error
	// err := db.Order("station_train_code, station_no").Find(&schedules).Error
	if err != nil {
		return err
	}

	// 打开 CSV 文件
	file, err := os.Create(filePath)
	if err != nil {
		return err
	}
	defer file.Close()

	writer := csv.NewWriter(file)
	defer writer.Flush()

	// 写入 CSV 表头
	header := []string{"train_no", "station_train_code", "from_station", "to_station", "total_num", "station_name", "start_time", "arrive_time", "stopover_time", "station_no"}
	err = writer.Write(header)
	if err != nil {
		return err
	}

	// 写入每条记录
	for _, schedule := range schedules {
		record := []string{
			schedule.TrainNo,
			schedule.StationTrainCode,
			schedule.FromStation,
			schedule.ToStation,
			strconv.Itoa(schedule.TotalNum),
			schedule.StationName,
			schedule.StartTime,
			schedule.ArriveTime,
			schedule.StopoverTime,
			schedule.StationNo,
		}
		err = writer.Write(record)
		if err != nil {
			return err
		}
	}

	return nil
}

// queryMatchingSchedules查询schedules_all中全部途径南京的列车
func queryMatchingSchedules(db *gorm.DB) ([]Schedule, error) {
	var schedules []Schedule

	// 查询 schedules_nj 中的所有 station_train_code
	var njSchedules []Schedule
	err := db.Table("schedules_nj").Select("station_train_code").Distinct().Scan(&njSchedules).Error
	if err != nil {
		return nil, err
	}

	// 提取 station_train_code 列表
	var stationTrainCodes []string
	for _, s := range njSchedules {
		stationTrainCodes = append(stationTrainCodes, s.StationTrainCode)
	}
	fmt.Println("station_train_code list:", len(stationTrainCodes))

	// 查询 schedules_all 中 station_train_code 在 njSchedules 中存在的记录
	err = db.Table("schedules_all").Where("station_train_code IN ?", stationTrainCodes).Find(&schedules).Error
	if err != nil {
		return nil, err
	}

	return schedules, nil
}
func main() {
	// BindX()
	// SortTrainsByStationTrainCode()
	// GetTrainList()
	// GetSchedule()
	// writeStationsToGeojson()
	// GetTravelSegment()
	// MakeTripsDataSimp()
	// MakeTripsDataMinute()
	MakeTripsDataSecond()
	//初始化数据库
	db := initDB()
	count, err := getCount(db)
	if err != nil {
		fmt.Println("Error counting records:", err)
		return
	}
	fmt.Println("nanjing records:", count)
	// 按照示例数据,将数据库时刻表保存数据到 CSV 文件
	// err = saveSchedulesToCSV(db, "schedules_nj.csv")
	// err = saveSchedulesToCSV(db, "schedules_all.csv")
	// if err != nil {
	// 	fmt.Println("Error saving to CSV:", err)
	// 	return
	// }
	// fmt.Println("CSV file generated successfully.")
	fmt.Println("All tables:")
	fmt.Println(db.Migrator().GetTables())
	db.Table("schedules_nj").Count(&count)
	fmt.Println("nj schedules:", count)
	db.Table("schedules_all").Count(&count)
	fmt.Println("all schedules:", count)
}
